#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"

#include <GL/gl.h>
#include <GL/glut.h>

#include "BList.h"
#include "BVector.h"
#include "geometrics.h"
#include "quaternion.h"
#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"
#include "SpecialTerm.h"
#include "ST_floatInterval.h"

#include "AWLocalViewport.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWScenario.h"
#include "AWBody.h"
#include "AWSceneBody.h"
#include "AWSensor.h"
#include "AWBrain.h"
#include "AWAgent.h"
#include "AWWorld.h"


extern void glutSolidBox(float dx,float dy,float dz);


void AW_SceneBody::operators(void)
{
	FeatureTerm *op;

	m_ontology->new_sort("rotate-operator","any",2,"speed","float","time","float");
	op=FeatureTerm::fromStringNOOS("(define (rotate-operator))",m_memory,m_ontology);

	op->defineFeatureValue("speed",new FeatureTerm((Symbol *)0,
												   new ST_floatInterval(m_ontology->get_sort("float-interval"),
																		new FeatureTerm((Symbol *)0,-180.0F,m_ontology),
																		new FeatureTerm((Symbol *)0,180.0F,m_ontology)),
												   m_ontology->get_sort("float-interval")));
	op->defineFeatureValue("time",new FeatureTerm((Symbol *)0,
												   new ST_floatInterval(m_ontology->get_sort("float-interval"),
																		new FeatureTerm((Symbol *)0,0,m_ontology),
																		0),
												   m_ontology->get_sort("float-interval")));
	m_ops.Add(op);

	m_ontology->new_sort("advance-operator","any",2,"speed","float","time","float");
	op=FeatureTerm::fromStringNOOS("(define (advance-operator))",m_memory,m_ontology);
	op->defineFeatureValue("speed",new FeatureTerm((Symbol *)0,
												   new ST_floatInterval(m_ontology->get_sort("float-interval"),
																		new FeatureTerm((Symbol *)0,-10.0F,m_ontology),
																		new FeatureTerm((Symbol *)0,10.0F,m_ontology)),
												   m_ontology->get_sort("float-interval")));
	op->defineFeatureValue("time",new FeatureTerm((Symbol *)0,
												   new ST_floatInterval(m_ontology->get_sort("float-interval"),
																		new FeatureTerm((Symbol *)0,0,m_ontology),
																		0),
												   m_ontology->get_sort("float-interval")));
	m_ops.Add(op);

	m_ontology->new_sort("send-operator","any",2,"receiver","symbol","content","symbol");
	op=FeatureTerm::fromStringNOOS("(define (send-operator))",m_memory,m_ontology);
	m_ops.Add(op);

	m_ontology->new_sort("scene-operator","any",1,"scene","symbol");
	op=FeatureTerm::fromStringNOOS("(define (scene-operator))",m_memory,m_ontology);
	m_ops.Add(op);
} /* AW_SceneBody::operators */ 


AW_SceneBody::AW_SceneBody(Ontology *O,FTKBase *Memory) : AW_Body(O,Memory) 
{
	operators();
	scene=new Symbol("none");
	
	class_name->set("AW_SceneBody");

} /* AW_SceneBody */ 


AW_SceneBody::AW_SceneBody(FILE *fp,Ontology *O,FTKBase *Memory) : AW_Body(O,Memory) 
{
	operators();
	scene=new Symbol("none");
	
	class_name->set("AW_SceneBody");

	load(fp);
} /* AW_SceneBody::AW_SceneBody */ 


bool AW_SceneBody::load(FILE *fp)
{
	if (!AW_Body::load(fp)) return false;
	scene=new Symbol(fp);

	return true;
} /* AW_SceneBody::load */ 


bool AW_SceneBody::save(FILE *fp)
{
	if (!AW_Body::save(fp)) return false;
	scene->save(fp);

	return true;
} /* AW_SceneBody::save */ 


void AW_SceneBody::draw(void)
{
	if (!scene->cmp("none")) {
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();

		/* Dibujar el cuerpo: */ 
		AW_Body::draw();

		glPopMatrix();
	} /* if */ 

} /* AW_SceneBody::draw */ 



void AW_SceneBody::draw_shadows(float lightpos[4])
{
	if (!scene->cmp("none")) {
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();

		/* Dibujar el cuerpo: */ 
		AW_Body::draw_shadows(lightpos);

		glPopMatrix();
	} /* if */ 

} /* AW_SceneBody::draw_shadows */ 




bool AW_SceneBody::ApplyOperator(FeatureTerm *op,float time,AW_Agent *a,AW_World *w)
{
	if (strcmp(op->getSort()->get(),"rotate-operator")==0) {
		Quaternion q;
		float axis[3]={0,1,0};
		float angle=op->featureValueQuick("amount")->getFloat();
		angle=float((angle*M_PI)/180);

		q.from_axis_angle(axis,angle*time);
		m_d.pre_multiply(&q);
		return true;
	} /* if */ 

	if (strcmp(op->getSort()->get(),"advance-operator")==0) {
		float v[4]={0,0,0,0},v2[4];
		v[2]=(op->featureValueQuick("amount")->getFloat())*time;
		
		m_d.rotate_vector(v,v2);

		m_pos.x+=v2[0];
		m_pos.y+=v2[1];
		m_pos.z+=v2[2];
		return true;
	} /* if */ 

	if (strcmp(op->getSort()->get(),"send-operator")==0) {
		Symbol *s1=0,*s2=0;
		FeatureTerm *f;

		f=op->featureValueQuick("receiver");
		if (f!=0) s1=f->getSymbol();
		f=op->featureValueQuick("content");
		if (f!=0) s2=f->getSymbol();
		if (s1==0 || s2==0) return false;
		w->sendmessage(new AW_Message(a->get_AgentName(),s1,s2));
		return true;
	} /* if */ 

	if (strcmp(op->getSort()->get(),"scene-operator")==0) {
		Symbol *s1=0;
		FeatureTerm *f;

		f=op->featureValueQuick("scene");
		if (f!=0) s1=f->getSymbol();
		if (s1==0) return false;
		scene->set(s1->get());
		return true;
	} /* if */ 

	return AW_Body::ApplyOperator(op,time,a,w);
} /* AW_SceneBody::ApplyOperator */ 



bool AW_SceneBody::is_a(char *c)
{
	if (strcmp(c,"AW_SceneBody")==0) return true;

	return AW_Body::is_a(c);
} /* AW_SceneBody::is_a */ 


bool AW_SceneBody::is_a(Symbol *c)
{
	if (c->cmp("AW_SceneBody")) return true;

	return AW_Body::is_a(c);
} /* AW_SceneBody::is_a */ 

